#include<arpa/inet.h>
#include<netinet/in.h>
#include<ctype.h>
#include"wrap.h"
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/socket.h>
#include<pthread.h>
/*
   实现多线程的网络通信
		1、子线程不能关闭监听文件描述符lfd，原因是子线程和主线程共享文件描述符
 */

typedef struct info
{
	int cfd; // 若为-1表示可用，大于0表示已被占用
	int idx; //索引
	pthread_t thread; // 
	struct sockaddr_in client;
}INFO;

INFO thInfo[1024];

//子线程回调函数
void *thread_work(void*arg)
{
	INFO *p = (INFO*)arg;
	printf("idx == [%d]\n",p->idx);
	
	int cfd = p->cfd;

	int n = 0;
	char buf[1024];
	int i = 0;	
	while(1)
	{
		//读数据
		memset(buf,0x00,sizeof(buf));	
		n = Read(cfd,buf,sizeof(buf));
		if(n<=0)
		{
			printf("read error or client closed,n==[%d]\n",n);
			Close(cfd);
			p->cfd = -1;
			pthread_exit(NULL);
		}
		printf("n==[%d],buf==[%s]\n",n,buf);
		for(i = 0;i<n;i++)
		{
			buf[i] = toupper(buf[i]);
		}
		//发送数据给客户端
		Write(cfd,buf,n);
	}
	//关闭通信文件描述符
	close(cfd);

	//退出线程
	pthread_exit(NULL);
}

void init_thInfo()
{
	int i = 0;
	for(i=0;i<1024;i++)
	{
		thInfo[i].cfd = -1;
	}
}

int findIndex()
{
	int i;
	for(i=0;i<1024;i++)
	{
		if(thInfo[i].cfd == -1)
		{
			break;
		}
	}
	if(i==1024)
	{
		return -1;
	}
	return i;
}



int main()
{
	//1、创建socket
	int lfd = Socket(AF_INET,SOCK_STREAM,0);	

	//2、绑定
	struct sockaddr_in serv;
	bzero(&serv,sizeof(serv));//初始化
	serv.sin_family = AF_INET;
	serv.sin_port = htons(6666);
	serv.sin_addr.s_addr = htonl(INADDR_ANY);
	Bind(lfd,(struct sockaddr*)&serv,sizeof(serv));
	//3、设置监听
	Listen(lfd,128);

	//初始化
	init_thInfo();

	//进入循环
	int ret;
	int cfd;
	pthread_t threadID;
	struct sockaddr_in client;
	while(1)
	{
		cfd = accept(lfd,NULL,NULL);

		//找数组中空闲的位置
		index = findIndex();
		if(idx==-1)
		{
			Close(cfd);
			continue;
		}
		//对空闲位置的元素的成员进行赋值
		thInfo[index].cfd = cfd;
		thInfo[index].idx = index;
		memcpy(&thInfo[index].client,&client,sizeof(client));

		//创建子线程
		ret = pthread_create(&thInfo[index].thread,NULL,thread_work,&thInfo[index]);
		if(ret != 0)
		{
			printf("creat thread error:[%s]\n",strerror(ret));
			exit(-1);
		}

		//设置子线程为分离属性
		pthread_detach(thInfo[index].thread);
	}
	//关闭监听文件描述付
	close(lfd);
	return 0;
}



